package com.medical.data.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.util.ConverterUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.medical.data.constEnum.FormItemEnum;
import com.medical.data.domain.FormItem;
import com.medical.data.domain.FormTemplate;
import com.medical.data.exception.MyException;
import com.medical.data.mapper.FormItemMapper;
import com.medical.data.service.FormItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medical.data.service.FormTemplateService;
import com.medical.data.service.TemplateFormService;
import com.medical.data.service.UserPermissionService;
import com.medical.data.utils.*;
import com.medical.data.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONString;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 表单基本组件 服务实现类
 * </p>
 *
 * @author cj
 * @since 2024-01-23
 */
@Service
@Slf4j
public class FormItemServiceImpl extends ServiceImpl<FormItemMapper, FormItem> implements FormItemService {

    @Autowired
    private FormTemplateService templateService;

    @Autowired
    private TemplateFormService templateFormService;

    @Autowired
    private SortUtils sortUtils;

    @Autowired
    private UserPermissionService userPermissionService;

    @Autowired
    private FormTemplateService formTemplateService;

    @Override
    public AddFormItemResultVo addFormItem(AddFormItemVo addFormItemVo) {
        userPermissionService.getFormPermission(templateFormService.getProjectIdByNodeId(addFormItemVo.getFormTemplateId()));
        FormItem formItem = new FormItem();
        AddFormItemResultVo addFormItemResultVo = new AddFormItemResultVo();
        //首先根据表单id查询该表单是否为可添加
        getForm(addFormItemVo.getFormTemplateId());
        if (ObjectUtil.isNull(addFormItemVo.getIsDisplayType())) {
            formItem.setIsDisplayType(false);
        }
        if (ObjectUtil.isNull(addFormItemVo.getIsHideType())) {
            formItem.setIsHideType(false);
        }
        //首先查询是否存在该组件名字了
        List<FormItem> list = baseMapper.selectList(Wrappers.<FormItem>lambdaQuery()
                .eq(FormItem::getFormTemplateId, addFormItemVo.getFormTemplateId())
                .eq(FormItem::getFormItemId, addFormItemVo.getFormItemId()).select(FormItem::getId));
        if (!CollectionUtils.isEmpty(list))
            throw new MyException(ResultCode.ERROR.getCode(), "该组件已存在了");
        //排序下标计算
        addFormItemVo.setSort(sortUtils.getInitialSortPosition(addFormItemVo.getFormTemplateId()));
        addFormItemVo.setIsSpecialType(this.isSpecialTypeItem(addFormItemVo));
        //新增
        BeanUtils.copyProperties(addFormItemVo, formItem);
/*        if (!ObjectUtils.isEmpty(addFormItemVo.getScheme())){
            formItem.setScheme(JSONObject.toJSONString(addFormItemVo.getScheme()));
        }else {
            formItem.setScheme("{}");
        }*/
        if (!CollectionUtils.isEmpty(addFormItemVo.getRegList())) {
            formItem.setRegList(JSONArray.toJSONString(addFormItemVo.getRegList()));
        } else {
            formItem.setRegList("[]");
        }
        log.info("========>{}", formItem);
        int insert = baseMapper.insert(formItem);
        if (insert < 1)
            throw new MyException(ResultCode.ERROR.getCode(), "新增失败");
        addFormItemResultVo.setSort(addFormItemVo.getSort())
                .setId(formItem.getId())
                .setRefreshAll(false)
                .setOperateSuccess(true);
        return addFormItemResultVo;
    }

    private Boolean isSpecialTypeItem(AddFormItemVo addFormItemVo) {
        // 随机编号
        if (addFormItemVo.getItemType() == FormItemEnum.RANDOM_NUMBER.getName()) {
            return true;
        }
        // 不允许重复
        if (addFormItemVo.getItemType() == FormItemEnum.RANDOM_NUMBER.getName()) {
            InputResultStructUtils builder = InputResultStructUtils.builder(addFormItemVo.getScheme());
            return builder.isNotRepeat();
        }
//        // 商品
        if (addFormItemVo.getItemType() == FormItemEnum.GOODS_SELECT.getName()) {
            return true;
        }
        // 预约时间
        if (addFormItemVo.getItemType() == FormItemEnum.RESERVE_DAY.getName() || addFormItemVo.getItemType() == FormItemEnum.RESERVE_TIME_RANGE.getName()) {
            return true;
        }
        // 投票
        if (addFormItemVo.getItemType() == FormItemEnum.CHECKBOX.getName() || addFormItemVo.getItemType() == FormItemEnum.RADIO.getName() || addFormItemVo.getItemType() == FormItemEnum.IMAGE_SELECT.getName()) {
            CheckboxSchemaStruct builder = CheckboxSchemaStruct.builder(addFormItemVo.getScheme());
            // 单选多选带名额
            if (builder.getConfig().getOptions().stream().anyMatch(item -> ObjectUtil.isNotNull(item.getQuotaSetting()))) {
                return true;
            }
            return builder.getConfig().isShowVoteResult();
        }
        return false;
    }

    @Override
    public Long getLastItemSort(String formId) {
        Page<FormItem> formItemEntityPage = baseMapper.selectPage(new Page<>(1, 1, false),
                Wrappers.<FormItem>lambdaQuery().eq(FormItem::getFormTemplateId, formId)
                        .orderByDesc(FormItem::getSort));
        FormItem first = CollUtil.getFirst(formItemEntityPage.getRecords());
        return ObjectUtil.isNull(first) ? 0 : first.getSort();
    }

    @Override
    public void updateFormItem(AddFormItemVo addFormItemVo) {
        userPermissionService.getFormPermission(templateFormService.getProjectIdByNodeId(addFormItemVo.getFormTemplateId()));
        FormItem formItem = new FormItem();
        //首先根据表单id查询该表单是否为可添加
        getForm(addFormItemVo.getFormTemplateId());
        addFormItemVo.setIsSpecialType(this.isSpecialTypeItem(addFormItemVo));
        if (ObjectUtil.isNull(addFormItemVo.getIsDisplayType())) {
            formItem.setIsDisplayType(false);
        }
        if (ObjectUtil.isNull(addFormItemVo.getIsHideType())) {
            formItem.setIsHideType(false);
        }
        //新增
        BeanUtils.copyProperties(addFormItemVo, formItem);
/*        if (!ObjectUtils.isEmpty(addFormItemVo.getScheme())){
            formItem.setScheme(JSONObject.toJSONString(addFormItemVo.getScheme()));
        }else {
            formItem.setScheme("{}");
        }*/
        if (!CollectionUtils.isEmpty(addFormItemVo.getRegList())) {
            formItem.setRegList(JSONArray.toJSONString(addFormItemVo.getRegList()));
        } else {
            formItem.setRegList("[]");
        }
        log.info("========>{}", formItem);
        int update = baseMapper.update(formItem, Wrappers.<FormItem>lambdaQuery().eq(FormItem::getFormItemId, addFormItemVo.getFormItemId()).orderByDesc(FormItem::getCreateTime));
        if (update < 1)
            throw new MyException(ResultCode.ERROR.getCode(), "修改失败");
    }

    @Override
    public AddFormItemResultVo formItemSort(FormItemSortVo formItemSortVo) {
        getForm(formItemSortVo.getFormTemplateId());
        if (ObjectUtils.isEmpty(formItemSortVo.getBeforePosition()) && ObjectUtils.isEmpty(formItemSortVo.getAfterPosition())) {
            return new AddFormItemResultVo();
        }
        FormItem formItem = baseMapper.selectOne(Wrappers.<FormItem>lambdaQuery().eq(FormItem::getFormItemId, formItemSortVo.getFormItemId()).eq(FormItem::getFormTemplateId, formItemSortVo.getFormTemplateId()).orderByDesc(FormItem::getCreateTime));
        Long sort = sortUtils.calcSortPosition(formItemSortVo.getBeforePosition(), formItemSortVo.getAfterPosition(), formItemSortVo.getFormTemplateId());
        if (sortUtils.sortAllList(formItemSortVo.getBeforePosition(), formItemSortVo.getAfterPosition(), formItemSortVo.getFormTemplateId(), sort)) {
            return new AddFormItemResultVo(formItem.getSort(), formItem.getId(), true, true);
        }
        formItem.setSort(sort);
        int b = baseMapper.updateById(formItem);
        return new AddFormItemResultVo(formItem.getSort(), formItem.getId(), BooleanUtils.toBoolean(b), false);
    }

    @Override
    public List<FormItem> getFormItem(String formId) {
        List<FormItem> list = baseMapper.selectList(Wrappers.<FormItem>lambdaQuery().eq(FormItem::getFormTemplateId, formId).orderByDesc(FormItem::getCreateTime));
        list.sort(Comparator.comparing(FormItem::getSort));
        return list;
    }

    @Override
    public void deleteFormItem(String formId, String formItemId) {
        userPermissionService.getFormPermission(templateFormService.getProjectIdByNodeId(templateFormService.getNodeIdByFormId(formId)));
        int delete = baseMapper.delete(Wrappers.<FormItem>lambdaQuery()
                .eq(FormItem::getFormTemplateId, formId)
                .eq(FormItem::getFormItemId, formItemId));
        if (delete < 1)
            throw new MyException(ResultCode.ERROR.getCode(), "删除失败");

    }

    @Override
    public PreviewFormItemVo previewFormItem(String formId) {
        FormTemplate formTemplate = templateService.getById(formId);
        if (ObjectUtils.isEmpty(formTemplate)) {
            throw new MyException(ResultCode.ERROR.getCode(), "该表单不存在");
        }
        List<FormItem> formItems = this.getFormItem(formId);
        PreviewFormItemVo previewFormItemVo = new PreviewFormItemVo().setFormItems(formItems)
                .setFormTemplate(formTemplate);
        return previewFormItemVo;
    }

    @Override
    public List<FormFieldVO> listFormFields(String formId) {
        List<FormItem> itemEntityList = this.list(Wrappers.<FormItem>lambdaQuery().eq(FormItem::getFormTemplateId, formId).eq(FormItem::getIsDisplayType, 0));
        itemEntityList.sort(Comparator.comparing(FormItem::getSort));
        // FormFieldVO 处理了部份组价默认显示label字段
        List<FormFieldVO> fields = itemEntityList.stream().map(FormFieldVO::new).collect(Collectors.toList());
        return fields;
    }

    @Override
    public void addAllFormItem(FormItem formItem) {
        if (templateService.getFormStatus(formItem.getFormId()).equals("0")) {
            userPermissionService.getFormPermission(templateFormService.getProjectIdByNodeId(templateFormService.getNodeIdByFormId(formItem.getFormId())));
        }
        //如果先前有组件记录了，就全部删除然后再新增
        LambdaQueryWrapper<FormItem> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(FormItem::getFormId, formItem.getFormId());
        List<FormItem> formItems = this.baseMapper.selectList(wrapper1);
        if (formItems.size() != 0) {
            int delete = this.baseMapper.delete(wrapper1);
            if (delete < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新组件失败");
            }
        }
        String scheme = formItem.getScheme();
        //做解析，因为每个组件的scheme不同，所以只能做部分解析
        String configString;
        JSONObject jsonObject = JSONObject.parseObject(scheme);
        if (jsonObject.containsKey("config")) {
            JSONObject configObject = jsonObject.getJSONObject("config");
            configString = JSONObject.toJSONString(configObject);
        } else {
            throw new MyException(ResultCode.ERROR.getCode(), "传参错误");
        }
        JSONArray listArray = new JSONArray();
        if (jsonObject.containsKey("list")) {
            listArray = jsonObject.getJSONArray("list");
        }
        for (int i = 0; i < listArray.size(); i++) {
            JSONObject listItem = listArray.getJSONObject(i);
            String compType = listItem.getString("compType");
            String formItemId = listItem.getString("id");
            String label = listItem.getString("label");
            FormItem formItem2 = new FormItem();
            formItem2.setFormId(formItem.getFormId());
            formItem2.setScheme(formItem.getScheme());
            formItem2.setConfig(configString);
            formItem2.setCompType(compType);
            formItem2.setOneItemId(formItemId);
            formItem2.setLabel(label);
            FormItem formItem1 = new FormItem();
            LambdaQueryWrapper<FormItem> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FormItem::getFormId, formItem.getFormId())
                    .eq(FormItem::getOneItemId, formItemId);
            formItem1 = this.baseMapper.selectOne(wrapper);
            //如果传的formId下有组件了，就执行更新
            if (!ObjectUtils.isEmpty(formItem1)) {
                int update = this.baseMapper.update(formItem2, wrapper);
                if (update < 1) {
                    throw new MyException(ResultCode.ERROR.getCode(), "更新组件失败");
                }
            } else {
                int insert = this.baseMapper.insert(formItem2);
                if (insert < 1) {
                    throw new MyException(ResultCode.ERROR.getCode(), "插入失败");
                }
            }
        }
    }

    @Override
    public FormItem getAllFormItem(String formId) {
        LambdaQueryWrapper<FormItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FormItem::getFormId, formId);
        FormItem formItem = new FormItem();
        List<FormItem> list = this.baseMapper.selectList(wrapper);
        formItem = list.get(0);
        return formItem;

    }

    @Override
    public Map<String, String> getAllFormItemByFormId(String formId) {
        Map<String, String> map = new HashMap<>();
        List<FormItem> list = new ArrayList<>();
        LambdaQueryWrapper<FormItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FormItem::getFormId, formId);
        list = this.baseMapper.selectList(wrapper);
        for (FormItem formItem : list) {
            map.put(formItem.getOneItemId(), formItem.getLabel());
        }
        return map;
    }

    @Override
    public String getLabelByFormId(String formItemId) {
        LambdaQueryWrapper<FormItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FormItem::getOneItemId, formItemId);
        return this.baseMapper.selectOne(wrapper).getLabel();
    }

    @Override
    public void shareFormItem(String originalFormId, String targetFormId) {
        LambdaQueryWrapper<FormItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FormItem::getFormId, originalFormId);
        List<FormItem> formItems = this.baseMapper.selectList(wrapper);
        List<FormItem> formItemList = new ArrayList<>();
        for (FormItem formItem : formItems) {
            FormItem formItem1 = new FormItem();
            formItem1.setFormId(targetFormId).setOneItemId(formItem.getOneItemId())
                    .setLabel(formItem.getLabel()).setConfig(formItem.getConfig())
                    .setSort(formItem.getSort()).setRegList(formItem.getRegList())
                    .setItemType(formItem.getItemType()).setPlaceholder(formItem.getPlaceholder())
                    .setRequired(formItem.getRequired()).setSpan(formItem.getSpan())
                    .setCompType(formItem.getCompType()).setScheme(formItem.getScheme())
                    .setSort(formItem.getSort()).setIsDelete(formItem.getIsDelete())
                    .setIsDisplayType(formItem.getIsDisplayType()).setIsHideType(formItem.getIsHideType())
                    .setIsSpecialType(formItem.getIsSpecialType()).setShowLabel(formItem.getShowLabel());
            formItemList.add(formItem1);
        }
        for (FormItem formItem : formItemList) {
            System.out.println(formItem.getFormId() + "," + formItem.getId());
            int insert = this.baseMapper.insert(formItem);
            if (insert < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "插入失败");
            }
        }
    }

    @Override
    public List<FormItem> getFormItemByFormId(String formId) {
        LambdaQueryWrapper<FormItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FormItem::getFormId, formId);
        FormItem formItem = new FormItem();
        return this.baseMapper.selectList(wrapper);
    }

    public FormTemplate getForm(String formId) {
        FormTemplate formTemplate = templateService.getById(formId);
        if (ObjectUtils.isEmpty(formTemplate)) {
            throw new MyException(ResultCode.ERROR.getCode(), "该表单不存在");
        }
        Boolean isAddItem = formTemplate.getIsAddItem();
        if (!isAddItem)
            throw new MyException(ResultCode.ERROR.getCode(), "该表单不可添加");
        return formTemplate;
    }
}
